using System;
using System.Collections.Generic;
using System.Text;
using DatabaseCode.Data;

namespace DatabaseCode.Maker
{
  class RelationshipMaker
  {
    //RelationShipクラス
    //  bool CanAdd(const DataMgr* data_mgr, const MgrDataMgr* mgr_data_mgr, 
    //              const TableType table_type, const void* data);
    //  bool CanRemove(const DataMgr* data_mgr, const MgrDataMgr* mgr_data_mgr, 
    //                  const TableType table_type, const void* data);
    public static string OutSource(D1_Headers headers)
    {
      StringBuilder addString = new StringBuilder();
      StringBuilder removeString = new StringBuilder();
      string managerName;
      string memberTable ;
      string memberHeader;
      string tableName;
      List<D_Reference> refs;

      //データヘッダの列挙(mgr_data.hなどの構造体部分)
      foreach(D2_Header header in headers.Headers)
      {
        managerName = header.Membername; // マネージャ名（例：mgr_data_mgr）
        //テーブル（構造体）の列挙
        foreach(D3_Table table in header.Tables)
        {
          tableName = Utility.MemberStringWithS_(table.Name); // テーブル名（例：item_kinds_）
          // CanAddの例
          //case Enums::kTableItem:
          //  for (i = 0; i < mgr_data_mgr->item_kinds_.table.size(); i++)
          //  {
          //    if (IsEqual(mgr_data_mgr->item_kinds_.table[i].code, ((Item*)data)->item_kind_code))
          //      break;
          //  }
          //  if (i == mgr_data_mgr->item_kinds_.table.size()) return false;
          //  break;
          addString.Append("  case Enums::kTable" + table.Name + ":\r\n");
          foreach (D4_Field field in table.Fields)
          {
            if (field.HasReference)
            {
              memberHeader = Utility.SeparateByUndercores(headers.GetHeaderName(field.RefTable));
              memberTable = Utility.MemberStringWithS_(field.RefTable);
              addString.Append("    for (i = 0; i < " + memberHeader +
                "->" + memberTable + ".table.size(); i++) {\r\n");
              addString.Append("      if (IsEqual(" + memberHeader + "->" +
                memberTable + ".table[i]." + field.RefMember + ", ((" +
                table.Name + "*)data)->" + field.Variablename + "))\r\n");
              addString.Append("        break;\r\n");
              addString.Append("    }\r\n");
              addString.Append("    if (i == " + memberHeader + "->" + memberTable + ".table.size()) return false;\r\n");
            }
          }
          addString.Append("    break;\r\n");

          // Removeの例
          //  case Enums::kTableItemKind:
          //    for (int i = 0; i < mgr_data_mgr->items_.table.size(); i++)
          //    {
          //      if (IsEqual(mgr_data_mgr->items_.At(i).item_kind_code,
          //                   ((ItemKind*)data)->code))
          //        return false;
          //    }
          //    break;
          removeString.Append("  case Enums::kTable" + table.Name + ":\r\n");
          foreach (D4_Field field in table.Fields)
          {
            if (headers.FindReference(table.Name, field.Variablename, out refs))
            {
              Debug.AddMessageLine("remove参照 " + 
                Utility.InsertSpacesToRight(table.Name + "." + field.Variablename, 14) + refs.Count + "件");
              foreach (D_Reference ref1 in refs)
              {
                memberTable = Utility.MemberStringWithS_(ref1.tablename);
                removeString.Append("    for (i = 0; i < " + ref1.headername + "->" + memberTable + 
                  ".table.size(); i++) {\r\n");
                removeString.Append("      if (IsEqual(" + ref1.headername + "->" + memberTable + 
                  ".At(i)." + ref1.membername + ", ((" + table.Name + "*)data)->" +
                  field.Variablename + "))\r\n");
                removeString.Append("        return false;\r\n");
                removeString.Append("    }\r\n");
              }
            }
          }
          removeString.Append("    break;\r\n");
        }
      }

      return @"//戻り値：参照に必要なデータがない場合は false を返す。
bool RelationShip::CanAdd
  (" + headers.GetManagerParameterString() + @", 
   const Enums::Table table_type, const void* data)
{
  unsigned int i;

  switch(table_type)
  {
" + addString.ToString() + 
@"  }
  return true;
}

//戻り値：他のデータによって参照されている場合は false を返す。
bool RelationShip::CanRemove
  (" + headers.GetManagerParameterString() + @", 
   const Enums::Table table_type, const void* data)
{
  unsigned int i;

  switch(table_type)
  {
" + removeString.ToString() + 
@"  }
  return true;
}";
    }


    /*コード出力例：
class MonDataMgr;
class MgrDataMgr;

class RelationShip {
public:
  bool CanAdd(MonDataMgr* mon_data_mgr, MgrDataMgr* mgr_data_mgr, 
              const Enums::Table table_type, const void* data);
  bool CanRemove(MonDataMgr* mon_data_mgr, MgrDataMgr* mgr_data_mgr, 
                 const Enums::Table table_type, const void* data);
};*/
    public static string OutHeader(D1_Headers headers)
    {
      string str = "";

      foreach (D2_Header h in headers.Headers)
      {
        str += "class " + h.Name + ";\r\n";
      }
      str += "\r\n";
      str += @"class RelationShip {
public:
  bool CanAdd(" + headers.GetManagerParameterString() + @",
              const Enums::Table table_type, const void* data);
  bool CanRemove(" + headers.GetManagerParameterString() + @",
                 const Enums::Table table_type, const void* data);
};";
      return str;
    }
  }
}
